#include "board.h"
#include "CPU_const.h"



/****************************************************************************************************/
/*                  S U P E R     H I G H     P U B L I C      F U N C T I O N S                    */
/****************************************************************************************************/
bool EK270::GetCurrentParameters(EKdata *pCurrData)
{
  if( !startEK() ) return false;   if(!OpenCLcastle()) return false;
//get current parameters
  if( !getPARAMdt(Time_adr,&ArchData.Time) ) return false;
  if( !getPARAMfl(VbT_adr,&ArchData.VbT) ) return false;
  if( !getPARAMfl(Vo_adr,&ArchData.Vo) ) return false;
  if( !getPARAMfl(p_adr,&ArchData.p) ) return false;
  if( !getPARAMfl(T_adr,&ArchData.T) ) return false;
//
  *pCurrData = ArchData; return true;
}


bool EK270::GetGasPassport(GASpassport *pGAS)
{
  if( !startEK() ) return false;   if(!OpenCLcastle()) return false;
//get current parameters
  if( !getPARAMfl(CO2_adr,&((*pGAS).CO2val)) ) return false;
  if( !getPARAMfl(H2_adr,&((*pGAS).H2val)) ) return false;
  if( !getPARAMfl(N2_adr,&((*pGAS).N2val)) ) return false;
  if( !getPARAMfl(Rhoc_adr,&((*pGAS).Rhoc)) ) return false;
//
  return true;
}





bool EK270::GetArMP(DataTime *pRecordTime, EKdata *pArData)
{
  if( !startEK() ) return false;      if(!OpenCLcastle()) return false;
  if( !getArch(pRecordTime,1,NofArMP) ) return false;
//
  *pArData = ArchData; return true;
}


bool EK270::GetArDay(DataTime *pRecordTime, EKdata *pArData)
{
  if( !startEK() ) return false;      if(!OpenCLcastle()) return false;
  if( !getArch(pRecordTime,1,NofArDay) ) return false;
//
  *pArData = ArchData; return true;
}


float EK270::PutCO2(float CO2percent) { return PutAnyoneParameter(CO2_adr,CO2percent); }

float EK270::PutH2(float H2percent)   { return PutAnyoneParameter(H2_adr,H2percent); }

float EK270::PutRhoc(float RhocVal)   { return PutAnyoneParameter(Rhoc_adr,RhocVal); }

float EK270::PutN2(float N2percent)   { return PutAnyoneParameter(N2_adr,N2percent); }



float EK270::PutAnyoneParameter(uint Adr, float Param)
{
//open castle  
  if(!startEK()) return 0;               if(!OpenSLcastle()) return 0;
//write & check parameter
  if(!putPARAMfl(Adr,Param)) return 0;   if(!getPARAMfl(Adr,&Param)) return 0;
//close castle
  CloseSLcastle();
//
  return Param;
}



/****************************************************************************************************/
/*                             P U B L I C      F U N C T I O N S                                   */
/****************************************************************************************************/

EK270::EK270(UARTbuf *pUART) {pUx = pUART; Z='0'; Atribute='0';  codSL=codCL=0;}
/****************************************************************************************************/

EK270::EK270(UARTbuf *pUART, uint CodSL, uint CodCL)
{ pUx = pUART;  Z='0';  Atribute='0';  codSL=CodSL;  codCL=CodCL;}
/****************************************************************************************************/

void EK270::setCodSL(uint CodSL) {codSL=CodSL;}
/****************************************************************************************************/

void EK270::setCodCL(uint CodCL) {codCL=CodCL;}
/****************************************************************************************************/


bool EK270::startEK(void)
{
  formBREAK();          askEK(TimeOutCmmn);
  formREQUEST();        if(askEK(TimeOutCmmn)) setID();
  formACK(Unorm,Yprog); return askEK(TimeOutCmmn);
}
/****************************************************************************************************/


bool EK270::OpenSLcastle(void)
{ uint StSL;
  if(!getPARAMui(StSL_adr,&StSL)) return false;
  if(!StSL) return putPARAMuiHex(CodSL_adr,codSL); else return true;
}
/****************************************************************************************************/

bool EK270::OpenCLcastle(void)
{ uint StCL;
  if(!getPARAMui(StCL_adr,&StCL)) return false;
  if(!StCL) return putPARAMuiHex(CodCL_adr,codCL); else return true;
}
/****************************************************************************************************/

bool EK270::CloseSLcastle(void)    { return putPARAMui(StSL_adr,0); }
/****************************************************************************************************/

bool EK270::CloseCLcastle(void)    { return putPARAMui(StCL_adr,0); }
/****************************************************************************************************/





bool EK270::getPARAMfl(uint Adr, float *pParam)
{
  formR1(Adr,1);
  if(askEK(TimeOutCmmn)) {*pParam = atof(str); return true;} else {return false;}
}
/****************************************************************************************************/


bool EK270::getPARAMui(uint Adr, uint *pParam)
{
  formR1(Adr,1);
  if(askEK(TimeOutCmmn)) {*pParam = atoi(str); return true;} else {return false;}
}
/****************************************************************************************************/


bool EK270::getPARAMdt(uint Adr, DataTime *pDT)
{
  formR1(Adr,1);
  if(askEK(TimeOutCmmn)) {StrToDataTime(pDT); return true;} else {return false;}
}
/****************************************************************************************************/

bool EK270::getArch(DataTime *pBgn, char NofStr, char NofArh)
{
  if(NofStr>MAXnosArMP) NofStr = MAXnosArMP; 
  formR3arch(NofArh,pBgn,NofStr);
  
  
  if(askEK(TimeOutArch)) {return true;} else {return false;}
  
}
/****************************************************************************************************/



bool EK270::putPARAMui(uint Adr, uint Param)
{ sprintf(&str,"%d",Param);  formW1(Adr);  return askEK(TimeOutCmmn); }
/****************************************************************************************************/

bool EK270::putPARAMuiHex(uint Adr, uint Param)
{ sprintf(&str,"%x",Param);  formW1(Adr);  return askEK(TimeOutCmmn); }
/****************************************************************************************************/

bool EK270::putPARAMfl(uint Adr, float Param)
{ sprintf(&str,"%f",Param);  formW1(Adr);  return askEK(TimeOutCmmn); }
/****************************************************************************************************/






/****************************************************************************************************/
/****************************************************************************************************/



/****************************************************************************************************/
/*                            P R I V A T E      F U N C T I O N S                                  */
/****************************************************************************************************/
void EK270::setID(void) { Z=str[3]; }
/****************************************************************************************************/
/****************************************************************************************************/


bool EK270::askEK(portTickType xTicksToWait)
{ (*pUx).SetBrdOISR();            /*poka tak!!!*/ RTS3_ON();/*U3_485_DE;*//*poka tak!!!*/          (*pUx).StartTransmite(); return check_Answer(xTicksToWait); }
/****************************************************************************************************/
/****************************************************************************************************/

void EK270::formBREAK(void)
{ sumXOR=SOH;   wrChar(SOH);  wrChar('B'); wrChar('0'); wrChar(ETX); wrChar(sumXOR); }
/****************************************************************************************************/

void EK270::formREQUEST(void)
{ wrChar('/');  wrChar('?'); wrChar('!'); wrChar(CR); wrChar(LF); }
/****************************************************************************************************/

void EK270::formACK(char u, char y)
{ wrChar(ACK);  wrChar(u); wrChar(Z); wrChar(y);  wrChar(CR); wrChar(LF); }
/****************************************************************************************************/

void EK270::formR1(uint Adr, usht NofPar)
{ 
  sumXOR=SOH;
  wrChar(SOH);  wrChar('R'); wrChar('1');  wrChar(STX);
  wrUShort(Adr/1000); wrChar(':'); wrUShort(Adr%1000); wrChar('('); wrUShort(1/*POKA!!!NofPar*/); wrChar(')');
  wrChar(ETX); wrChar(sumXOR);
}
/****************************************************************************************************/

void EK270::formR3arch(char NofArch, DataTime *pBgn, char NofStr)
{
  sumXOR=SOH;
  wrChar(SOH);  wrChar('R'); wrChar('3');  wrChar(STX);
  wrChar('0'+NofArch); wrChar(':');  wrChar('V');  wrChar('.');  wrChar(Atribute);
  wrChar('('); wrChar('3'); wrChar(';'); 
  wrDataTime(pBgn); wrChar(';'); wrChar(';'); wrUShort(NofStr); wrChar(')');
  wrChar(ETX); wrChar(sumXOR);
}
/****************************************************************************************************/


void EK270::formW1(uint Adr)
{ 
  sumXOR=SOH;
  wrChar(SOH);  wrChar('W'); wrChar('1');  wrChar(STX);
  wrUShort(Adr/1000); wrChar(':'); wrUShort(Adr%1000); wrChar('('); wrString(&str); wrChar(')');
  wrChar(ETX); wrChar(sumXOR);
}
/****************************************************************************************************/




/****************************************************************************************************/





void EK270::wrChar(char symbol)  { (*pUx).WrBufOut(symbol); sumXOR ^= symbol; }
/****************************************************************************************************/

void EK270::wrString(char *pSTR)
{ uint strLen, ui1;
//string length set up & checking   
  strLen = strlen(pSTR); if(!strLen || strLen>50) return;
//fill output buffer & calculating BCC
  for(ui1=0; ui1<strLen; ++ui1) {wrChar(*(pSTR+ui1));}
}
/****************************************************************************************************/

void EK270::wrUShort(usht num)
{ uint del=10000;
  while(del!=1) {if(num/del) break; del/=10;}
  while(del) {wrChar('0'+num/del); num%=del; del/=10;}
}
/****************************************************************************************************/

void EK270::wrDataTime(DataTime *pDT)
{
  wrChar('2'); wrChar('0'); wrDTval((*pDT).year); wrChar('-');
  wrDTval((*pDT).mnth); wrChar('-'); wrDTval((*pDT).date); wrChar(',');
  wrDTval((*pDT).hour); wrChar(':'); wrDTval((*pDT).min); wrChar(':'); wrDTval((*pDT).sec);
}
/****************************************************************************************************/

/*
void EK270::wrDataTime(DataTime *pDT)
{
  wrChar('2'); wrChar('0'); wrDTval((*pDT).year); wrChar('-');
  wrDTval((*pDT).mnth); wrChar('-'); wrDTval((*pDT).date); wrChar(',');
  wrDTval((*pDT).hour); wrChar(':'); wrDTval((*pDT).min); wrChar(':'); wrDTval((*pDT).sec);
}
/ ****************************************************************************************************/

/****************************************************************************************************/


void EK270::wrDTval(char DTval)
{ if(DTval>99) DTval=99;    wrChar('0'+DTval/10); wrChar('0'+DTval%10); }
/****************************************************************************************************/
/****************************************************************************************************/

bool EK270::check_Answer(portTickType xTicksToWait)
{ 
  static uint InInd=0, InEnd=0; 
  
  char symbol, indx=0, posa = Idle, column=0;

  while(posa!=Exit && posa!=ErrExit)
   {
//symbol wait
     if( InInd==InEnd && !(*pUx).RecieveIndI(&InEnd,xTicksToWait) )
       { posa = ErrExit;  symbol=0; }
      else
       { symbol=(*pUx).RdBufIn(InInd);  (*pUx).next(&InInd); }
//symbol check
     if(posa==wtBCC) { posa =Exit; symbol=0; }
     switch(symbol)
      { 
        case(ACK):  if(posa==Idle) {posa = Exit;} else {posa = ErrExit;}
                  break;
        case(NAK):  posa = ErrExit;
                  break;
        case('/'):  if(posa==Idle) {posa = wrID;} else {posa = ErrExit;}
                  break;
        case(SOH):  if(posa==Idle) {posa = wrCom;} else {posa = ErrExit;}
                  break;
        case(STX):  if(posa==Idle)    {posa = wrDat;   break;}
                    if(posa==wrCom)   {posa = wtOpBkt; break;}
                    posa = ErrExit; 
                  break;

        case('('):  if(posa==Idle)    {break;}
                    if(posa==wrDat || posa==wtETX)   {indx=0; posa = wrPrm; ++column;  break;}
                    if(posa==wtOpBkt) {posa = wrPrm;   break;}
                    posa = ErrExit;
                  break;

        case(')'):  if(posa==Idle)    {break;}
                    if(posa==wrPrm)   {posa = wtETX; str[indx] = 0; ParamSet(column); break;}
                    posa = ErrExit;
                  break;
                  
        case(CR) :  if(posa==Idle)  {break;}
                    if(posa==wrID)    {posa = wtLFend; break;}
                    if(posa==wrDat || posa==wtETX)   {posa = wtLF;    break;}
                    posa = ErrExit; 
                  break;

        case(LF) :  if(posa==Idle)  {break;}
                    if(posa==wtLFend) {posa = Exit;    break;}
                    if(posa==wtLF)    {posa = wtETX;   break;}
                    posa = ErrExit; 
                  break;
        case(ETX):
        case(EOT):  if(posa==wtETX) {posa = wtBCC;} else {posa = ErrExit;}
                  break;
          default:  if(posa==wrID || /*posa==wrCom ||*/ posa==wrPrm || posa==wrDat)
                      { str[indx] = symbol; if(indx<strSize-1) ++indx; }
      };/*switch(symbol)*/
    };/*while(posa!=Exit && posa!=ErrExit)*/
  //str[indx] = 0;
  if(posa==Exit) {return true;} else {return false;}
//
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

void EK270::ParamSet(char col)
{
  switch(col)
   {
     case(1)      : if(str[0]=='#') {ArchData.err = atoi(&str[1]);} else {ArchData.err = 0;} break;
     case(colTime): StrToDataTime(&ArchData.Time); break;
     case(colVbT) : ArchData.VbT = atof(str);      break;
     case(colVo)  : ArchData.Vo  = atof(str);      break;
     case(colpMP) : ArchData.p   = atof(str);      break;
     case(colTMP) : ArchData.T   = atof(str);      break;
    }/*switch(col)*/
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/


void EK270::StrToDataTime(DataTime *pDT)
{
  (*pDT).year = StrToChar(2);  (*pDT).mnth = StrToChar(5);  (*pDT).date = StrToChar(8);
  (*pDT).hour = StrToChar(11); (*pDT).min  = StrToChar(14); (*pDT).sec  = StrToChar(17);
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/


char EK270::StrToChar(uint StrShft)    { return (str[StrShft]-'0')*10 + (str[StrShft+1]-'0'); }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/